package com.github.prontera.service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.OffsetDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.github.prontera.Shift;
import com.github.prontera.StatusCode;
import com.github.prontera.common.token.PasswordHashUtil;
import com.github.prontera.domain.Activity;
import com.github.prontera.domain.Client;
import com.github.prontera.domain.ClientAccount;
import com.github.prontera.domain.ClientActivity;
import com.github.prontera.domain.ClientCoterie;
import com.github.prontera.domain.ClientInvitation;
import com.github.prontera.domain.ClientRent;
import com.github.prontera.domain.ClientTask;
import com.github.prontera.domain.ClientVideo;
import com.github.prontera.domain.ClientWechat;
import com.github.prontera.domain.Coterie;
import com.github.prontera.domain.Issue;
import com.github.prontera.domain.IssueAnswer;
import com.github.prontera.domain.SystemAccount;
import com.github.prontera.domain.SystemBean;
import com.github.prontera.domain.TalentOrder;
import com.github.prontera.domain.Task;
import com.github.prontera.domain.enums.AppSmsTemplateEnum;
import com.github.prontera.domain.enums.ClientConsumeTypeEnum;
import com.github.prontera.domain.enums.ClientTypeEnum;
import com.github.prontera.domain.enums.ConsumeLevelTypeEnum;
import com.github.prontera.domain.enums.ConsumeSmallTypeEnum;
import com.github.prontera.domain.enums.ConsumeTypeEnum;
import com.github.prontera.domain.enums.DictTypeEnum;
import com.github.prontera.domain.enums.OrderAcceptStatusEnum;
import com.github.prontera.domain.enums.OrderStatusEnum;
import com.github.prontera.domain.enums.PayChannelEnum;
import com.github.prontera.domain.enums.PayStatusEnum;
import com.github.prontera.domain.enums.RealAuthStatusEnum;
import com.github.prontera.domain.enums.SystemAccountStatusEnum;
import com.github.prontera.domain.enums.SystemAccountTypeEnum;
import com.github.prontera.domain.enums.TalentOrderTypeEnum;
import com.github.prontera.domain.enums.UserStatusEnum;
import com.github.prontera.domain.enums.VipStatusEnum;
import com.github.prontera.domain.enums.YesOrNoEnum;
import com.github.prontera.model.ConsumeMessageTemplate;
import com.github.prontera.model.request.LocationRequest;
import com.github.prontera.model.request.UserLoginRequest;
import com.github.prontera.persistence.ClientAccountMapper;
import com.github.prontera.persistence.ClientActivityMapper;
import com.github.prontera.persistence.ClientMapper;
import com.github.prontera.persistence.ClientRentMapper;
import com.github.prontera.persistence.CrudMapper;
import com.github.prontera.persistence.TalentOrderMapper;
import com.github.prontera.util.DateTimeUtil;
import com.github.prontera.util.RandomStringGenerator;
import com.github.prontera.util.ShareCodeUtil;

/**
 * 客户端
 */
@Service
public class ClientService extends CrudServiceImpl<Client> {

	@Autowired
	private ClientAccountService clientAccountService;
	@Autowired
	private ClientMapper mapper;
	@Autowired
	private ConsumeService consumeService;
	@Autowired
	private ActivityService activityService;
	@Autowired
	private ClientTaskService clientTaskService;
	@Autowired
	private ClientWechatService clientWechatService;
	@Autowired
	private ClientInvitationService clientInvitationService;
	@Autowired
	private TalentOrderMapper talentOrderMapper;
	@Autowired
	private TalentOrderService talentOrderService;
	@Autowired
	private CoterieService coterieService;
	@Autowired
	private IssueAnswerService issueAnswerService;
	@Autowired
	private ClientAccountMapper clientAccountMapper;
	@Autowired
	private ClientActivityMapper clientActivityMapper;
	@Autowired
	private SystemAccountService systemAccountService;
	@Autowired
	private ClientCoterieService clientCoterieService;
	@Autowired
	private SystemBeanService systemBeanService;
	@Autowired
	private SystemDiamondService systemDiamondService;
	@Autowired
	private ClientVideoService clientVideoService;
	@Autowired
	private AppSmsService appSmsService;
	@Autowired
	private ClientRentMapper clientRentMapper;
	@Autowired
	private DownloadComponent downloadComponent;
	@Autowired
	private TaskService taskService;
	@Autowired
	private ClientConsumeService clientConsumeService;
	
	@Autowired
	public ClientService(CrudMapper<Client> mapper) {
		super(mapper);
	}
	
	/**
	 * 计算每日消费收益
	 */
	public int updateCalculateDayIncome(){
		return mapper.updateCalculateDayIncome();
	}
	
	public void pushClient(Client client) {
		client.setId(null);
		insert(client);
		ClientAccount clientAccount=new ClientAccount();
		clientAccount.setClientId(client.getId());
		clientAccountService.insert(clientAccount);
		List<ClientRent> clientRents= clientRentMapper.findGroup();
		int max=clientRents.size();
        int s1 = new Random().nextInt(max)%(max-0+1) + 0;
        int s2 = new Random().nextInt(max)%(max-0+1) + 0;
        int s3 = new Random().nextInt(max)%(max-0+1) + 0;
		
        ClientRent clientRent1=clientRents.get(s1);
        ClientRent clientRent2=clientRents.get(s2);
        ClientRent clientRent3=clientRents.get(s3);
        
        clientRent1.setClientId(client.getId());
        clientRent2.setClientId(client.getId());
        clientRent3.setClientId(client.getId());
        
        clientRentMapper.insert(clientRent1);
        clientRentMapper.insert(clientRent2);
        clientRentMapper.insert(clientRent3);
        
        
        downloadComponent.getUserInfo(client.getUid());
	}
	
	public List<Client> findGeoClient(Client client){
		return mapper.findGeoClient(client);
	}
	
	/**
	 * 获取首页达人信息
	 */
	public List<Client> talentFind(Client client){
		return mapper.talentFind(client);
	};
	
	/**
	 * 获取用户带有达人分类得标签
	 */
	public Client getRentClient(Long clientId,Long lookClientId){
		Client client=new Client();
		client.setClientId(clientId);
		client.setLookClientId(lookClientId);
		return mapper.getRentClient(client);
	}
	
	/**
	 * 查看用户视频
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean lookVideo(Long clientId, Integer beanCount, Long videoId) {
		BigDecimal amount=CommonDict.get(DictTypeEnum.BEAN_CHANGE_MONEY.getDesc(), DictTypeEnum.BEAN_CHANGE_MONEY.getDesc()).getValue();
		
		//扣除查看用户唐豆豆
		if(!updateMyBean(clientId,(-1*beanCount))){
			Shift.fatal(StatusCode.LESS_THAN_BEAN, "唐豆豆不足!");
		}
		
		IssueAnswer findIssueAnswer=new IssueAnswer();
		findIssueAnswer.setId(videoId);
		IssueAnswer issueAnswer=issueAnswerService.findOne(findIssueAnswer);
		
		if(issueAnswer==null){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "videoId错误!");
		}
		
		ClientVideo clientVideo=new ClientVideo();
		clientVideo.setClientId(clientId);
		clientVideo.setLookClientId(issueAnswer.getClientId());
		clientVideo.setProductId(videoId);
		clientVideo.setPayAmount(amount);
		clientVideoService.insert(clientVideo);
		
		//给用户1个唐豆豆
		BigDecimal cashAmount=amount.divide(new BigDecimal(beanCount)).divide(new BigDecimal("0.1"));//1个唐豆豆, 0,1
		//支出
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.LOOK_VEDIO, MessageFormat.format(ConsumeMessageTemplate.MSG_LOOK_VIDEO, beanCount),ConsumeLevelTypeEnum.BEAN,beanCount, null,ConsumeTypeEnum.OUTCOME,null);
		//收入
		consumeService.insertConsume(issueAnswer.getClientId(),ConsumeSmallTypeEnum.R_LOOK_VEDIO, MessageFormat.format(ConsumeMessageTemplate.R_MSG_LOOK_VIDEO, cashAmount),ConsumeLevelTypeEnum.WITHDRAWALS,null, cashAmount,ConsumeTypeEnum.INCOME,null);
		//收入
		consumeService.insertConsume(issueAnswer.getIssureClientId(),ConsumeSmallTypeEnum.RR_LOOK_VEDIO, MessageFormat.format(ConsumeMessageTemplate.RR_MSG_LOOK_VIDEO, cashAmount),ConsumeLevelTypeEnum.WITHDRAWALS,null, cashAmount,ConsumeTypeEnum.INCOME,null);
		
		updateCashAmount(issueAnswer.getClientId(), cashAmount);
		
		updateCashAmount(issueAnswer.getIssureClientId(), cashAmount);
		
		if(!issueAnswerService.updateViewCount(videoId)) {
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
		}
		if(!clientAccountService.updateAccount(new ClientAccount(){

			private static final long serialVersionUID = 1L;
			{
				setClientId(issueAnswer.getClientId());
				setVedioNumber(1);
				setVedioMoney(cashAmount);
			}
		})){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
		}
		SystemBean systemBean=new SystemBean();
		systemBean.setBean(8);
		systemBean.setClientId(clientId);
		systemBeanService.insert(systemBean);
		return true;
	}
	
	/**
	 * 查看用户圈子
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean lookCoterie(long clientId,Integer beanCount,long coterieId){
		BigDecimal amount=CommonDict.get(DictTypeEnum.BEAN_CHANGE_MONEY.getDesc(), DictTypeEnum.BEAN_CHANGE_MONEY.getDesc()).getValue();
		//扣除查看用户唐豆豆
		if(!updateMyBean(clientId,(-1*beanCount))){
			Shift.fatal(StatusCode.LESS_THAN_BEAN, "唐豆豆不足!");
		}
		
		Coterie	coterie= coterieService.get(coterieId);
		if(coterie==null){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "coterieId参数错误!");
		}
		
		ClientCoterie clientCoterie=new ClientCoterie();
		clientCoterie.setClientId(clientId);
		clientCoterie.setCoterieId(coterieId);
		clientCoterie.setFollowCoterieClientId(coterie.getClientId());
		
		//给发圈子用户1个唐豆豆
		BigDecimal cashAmount=amount.divide(new BigDecimal(beanCount)).divide(new BigDecimal("0.1"));//1个唐豆豆, 0,1
		
		//支出
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.VIEW_COTERIE, MessageFormat.format(ConsumeMessageTemplate.MSG_LOOK_COTERIE, cashAmount),ConsumeLevelTypeEnum.BEAN,beanCount, null,ConsumeTypeEnum.OUTCOME,null);
		//收入
		consumeService.insertConsume(coterie.getClientId(),ConsumeSmallTypeEnum.VIEW_COTERIE, MessageFormat.format(ConsumeMessageTemplate.R_MSG_LOOK_COTERIE, cashAmount),ConsumeLevelTypeEnum.WITHDRAWALS,null, cashAmount,ConsumeTypeEnum.INCOME,null);
		
		if(clientCoterieService.insert(clientCoterie)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "扣除用户唐豆豆错误!");
		}
		if(!coterieService.updateViewCount(coterieId)) {
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
		}
		
		updateCashAmount(coterie.getClientId(), cashAmount);
		
		if(!clientAccountService.updateAccount(new ClientAccount(){

			private static final long serialVersionUID = 1L;
			{
				setClientId(coterie.getClientId());
				setCoterieNumber(1);
				setCoterieMoney(cashAmount);
			}
		})){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
		}
		SystemBean systemBean=new SystemBean();
		systemBean.setBean(9);
		systemBean.setClientId(clientId);
		systemBeanService.insert(systemBean);
		return true;
	}
	
	/**
	 * 查看用户微信
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean lookWechat(long clientId,BigDecimal amount,long lookClientId,boolean hasBalancePay){
		if(hasBalancePay){
			if(!updateAmount(clientId, amount.multiply(new BigDecimal(-1)))){
				Shift.fatal(StatusCode.LESS_THAN_BALANCE, "余额不足!");
			}
		}
		ClientWechat clientWechat=new ClientWechat();
		clientWechat.setClientId(clientId);
		clientWechat.setLookClientId(lookClientId);
		if(clientWechatService.count(clientWechat)==0){
			if(!clientWechatService.insert(clientId, lookClientId, amount)) {
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
			}
			boolean success=consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.LOOK_WECHAT,MessageFormat.format(ConsumeMessageTemplate.MSG_LOOK_WECHAT, amount) ,ConsumeLevelTypeEnum.DIRECT_CONSUME, null, amount,ConsumeTypeEnum.OUTCOME,null);
			if(!success) {
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
			}
			if(!updateCount(new Client(){
				private static final long serialVersionUID = 1L;
				{
					setId(lookClientId);
					setWechatCount(1);
				}
			})){
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
			};
			if(!clientAccountService.updateAccount(new ClientAccount(){

				private static final long serialVersionUID = 1L;
				{
					setClientId(lookClientId);
					setWechatMoney(amount);
				}
			})){
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
			}
			success=consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.R_LOOK_WECHAT,MessageFormat.format(ConsumeMessageTemplate.R_MSG_LOOK_WECHAT, amount) ,ConsumeLevelTypeEnum.WITHDRAWALS, null, amount,ConsumeTypeEnum.OUTCOME,null);
			if(!success) {
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误");
			}
		}
		Client client = getRentClient(lookClientId,null);
		if (client == null) {
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"用户不存在");
		}
		String code = new RandomStringGenerator(6,true).getNewString();
		Map<String, Object> arguments=new HashMap<String, Object>();
		arguments.put("val_code", code);
		appSmsService.sendToUID(arguments, client.getMobile(),AppSmsTemplateEnum.LOOK_WECHAT,code,null);
		return true;
	}
	
	@Autowired
	private IssueService issueService;
	
	/**
	 * 发起红包提问支付
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean payIssue(long clientId,BigDecimal amount,long issueId,boolean hasBalancePay){
		if(hasBalancePay){
			if(!updateAmount(clientId,amount.multiply(new BigDecimal(-1)))){
				Shift.fatal(StatusCode.LESS_THAN_BALANCE, "余额不足!");
			}
		}
		Issue issue=issueService.get(issueId);
		if(issue==null){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "提问不存在!");
		}
		//更新提问红包得支付状态, 
		Issue updateIssue=new Issue();
		updateIssue.setId(issueId);
		updateIssue.setHasPaySuccess(YesOrNoEnum.YES);
		issueService.update(updateIssue);
		//step: 将钱转入到系统账户
		systemAccountService.insertAccount(clientId,issue.getAcceptorId(),updateIssue.getId(), amount,SystemAccountTypeEnum.ISSUE);
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.ISSSUE_PAY, MessageFormat.format(ConsumeMessageTemplate.MSG_ISSUE_PAY, amount),hasBalancePay?ConsumeLevelTypeEnum.BALANCE:ConsumeLevelTypeEnum.DIRECT_CONSUME, null, amount,ConsumeTypeEnum.OUTCOME,null);
		return hasBalancePay;
	}
	
	/**
	 * 确认达人订单,
	 * 1:从系统账户转款给达人
	 * 2:给消费者上线提成
	 * 3:给达人增加收入记录
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean confirmTalent(TalentOrder talentOrder){
		if(talentOrder==null){
			Shift.fatal(StatusCode.LESS_THAN_BALANCE, "talendOrderId参数错误!");
		}
		talentOrder.setAcceptStatus(OrderAcceptStatusEnum.FINISHED);
		talentOrder.setStatus(OrderStatusEnum.FINISHED);
		if(talentOrderMapper.update(talentOrder)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "更新订单状态错误");
		}
//		ClientInvitation clientInvitation=new ClientInvitation();
//		clientInvitation.setPassiveClientId(talentOrder.getAcceptClientId());
//		ClientInvitation findClientInvitation=clientInvitationService.findOne(clientInvitation);
//		if(findClientInvitation!=null){//当前注册用户是被别人邀请得用户
//			//理解为下线得购买VIP记录
//			BigDecimal decimal=CommonDict.get(DictTypeEnum.SUBORDINATE_TALENT.getDesc(), DictTypeEnum.SUBORDINATE_TALENT.getDesc()).getValue();
//			String lable=MessageFormat.format(ConsumeMessageTemplate.MSG_SUBORDINATE_BUY_TALENT,  talentOrder.getAmount().divide(decimal.multiply(new BigDecimal(100))));
//			consumeService.insertConsume(findClientInvitation.getPassiveClientId(),ConsumeSmallTypeEnum.SUBORDINATE_TALENT,lable ,ConsumeLevelTypeEnum.INCOME, null, talentOrder.getAmount(),ConsumeTypeEnum.INCOME,null);
//			if(!clientAccountService.updateAccount(new ClientAccount(){
//				private static final long serialVersionUID = 1L;
//				{
//					setClientId(findClientInvitation.getPassiveClientId());
//					setFollowTalentMoney( talentOrder.getAmount());
//					setFollowNumber(1);
//				}
//			})){
//				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
//			}
//		}
		
		String lable=MessageFormat.format(ConsumeMessageTemplate.R_MSG_TAKE_IN_TALENT,  talentOrder.getAmount());
		consumeService.insertConsume(talentOrder.getAcceptClientId(),ConsumeSmallTypeEnum.R_BUY_TALEND, lable,ConsumeLevelTypeEnum.WITHDRAWALS, null, talentOrder.getAmount(),ConsumeTypeEnum.INCOME,null);
		
		SystemAccount systemAccount=systemAccountService.findAccount(talentOrder.getClientId(), talentOrder.getId(), SystemAccountTypeEnum.TALEND);
		//转给达人
		updateCashAmount(talentOrder.getAcceptClientId(), systemAccount.getAmount());
		
		ClientAccount clientAccount=new ClientAccount();
		clientAccount.setClientId(talentOrder.getAcceptClientId());
		clientAccount.setTradeMoney(talentOrder.getAmount());
		clientAccountService.updateAccount(clientAccount);
		
		//将系统账户更新到结束状态
		systemAccount.setStatus(SystemAccountStatusEnum.ACCEPTD);
		systemAccount.setAcceptorTime(OffsetDateTime.now());
		systemAccountService.update(systemAccount);
		
		talentOrderService.updateMemoryOrder(talentOrder);

		//添加返利--->统计/基础数据
		//更新消费等级--->记录消费
		updateLevel(talentOrder.getClientId(),1);
		
		clientConsumeService.insert(talentOrder.getAcceptClientId(), talentOrder.getAmount(), talentOrder.getId(),ClientConsumeTypeEnum.TALEND_INCOME);
		clientConsumeService.insert(talentOrder.getClientId(), talentOrder.getAmount(), talentOrder.getId(),ClientConsumeTypeEnum.TALEND_CONSUME);
		
		return true;
	}
	
	public boolean updateLevel(Long clientId,Integer level) {
		return mapper.updateLevel(clientId,level)>0;
	}
	
	/**
	 * 发起租达人信息
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean buyTalent(long clientId,long talendOrderId,boolean hasBalancePay,PayChannelEnum payChannelEnum){
		TalentOrder talentOrder=talentOrderMapper.get(talendOrderId);
		if(talentOrder==null){
			Shift.fatal(StatusCode.LESS_THAN_BALANCE, "talendOrderId参数错误!");
		}
		talentOrder.setPayChannel(payChannelEnum);
		if(hasBalancePay){
			if(!updateAmount(clientId,talentOrder.getAmount().multiply(new BigDecimal(-1)))){
				Shift.fatal(StatusCode.LESS_THAN_BALANCE, "余额不足!");
			}
		}
		talentOrder.setAmount(talentOrder.getAmount());
		talentOrder.setPayStatus(PayStatusEnum.PAYMENT);
		talentOrder.setType(TalentOrderTypeEnum.TALENT);
		talentOrder.setStatus(OrderStatusEnum.CONFIRMED);
		talentOrder.setAcceptStatus(OrderAcceptStatusEnum.WAIT_ACCEPT);
		if(talentOrderMapper.update(talentOrder)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "添加订单错误");
		}
		
		talentOrderService.updateMemoryOrder(talentOrder);
		
		String lable=MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_TALENT,  talentOrder.getAmount());
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.BUY_TALEND, lable,ConsumeLevelTypeEnum.WITHDRAWALS, null, talentOrder.getAmount(),ConsumeTypeEnum.OUTCOME,null);
		//将该笔支付金额列入系统资金池
		SystemAccount systemAccount=new SystemAccount();
		systemAccount.setAmount(talentOrder.getAmount());
		systemAccount.setAcceptorId(talentOrder.getAcceptClientId());
		systemAccount.setStatus(SystemAccountStatusEnum.WAITE_ACCEPT);
		systemAccount.setType(SystemAccountTypeEnum.TALEND);
		systemAccount.setProductId(talentOrder.getId());
		systemAccount.setClientId(clientId);
		systemAccountService.insert(systemAccount);
		return true;
	}
	
	/**
	 * 活动
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean buyActivity(long clientId,BigDecimal amount,long activityId,boolean hasBalancePay){
		Activity activity=activityService.get(activityId);
		if(activity==null){
			Shift.fatal(StatusCode.PRODUCT_NOT_EXITS, "商品不存在");
		}
		if(activity.getDiscountAmount().doubleValue()!=amount.doubleValue()){
			Shift.fatal(StatusCode.PRICE_DIFFER, "价格不一致,本次购买失败");
		}
		if(activity.getEndTime()!=null&&OffsetDateTime.now().isAfter(activity.getEndTime())){//
			Shift.fatal(StatusCode.EXCEED_PURCHASE_TIME, "已超过购买时间,欢迎下次购买");
		}
		if(activity.getStartTime()!=null&&OffsetDateTime.now().isBefore(activity.getStartTime())){//
			Shift.fatal(StatusCode.NO_PURCHASE_TIME, "未到购买时间,请稍后购买");
		}
		ClientActivity clientActivity=new ClientActivity();
		clientActivity.setActivityId(activityId);
		clientActivity.setClientId(clientId);
		if(clientActivityMapper.count(clientActivity)>0){
			Shift.fatal(StatusCode.ORADE_BU_ACTIVITY, "用户已经参与活动!");
		}
		if(!activityService.buyActivity(activityId, 1, clientId,amount)){
			Shift.fatal(StatusCode.INSUFFICIENT_STOCK, "该商品已罄售,欢迎下次购买");
		}
		if(hasBalancePay){
			if(!updateAmount(clientId, amount.multiply(new BigDecimal(-1)))){
				Shift.fatal(StatusCode.LESS_THAN_BALANCE, "余额不足!");
			}
		}
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.TAKE_ACTIVITY,MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_ACTIVITY, amount) ,ConsumeLevelTypeEnum.DIRECT_CONSUME, null, amount,ConsumeTypeEnum.OUTCOME,null);
		return true;
	}
	
	/**
	 * 充值唐豆
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Client buyBean(long clientId,BigDecimal amount){
		Client client=new Client();
		client.setId(clientId);
		client.setBBean(amount.multiply(CommonDict.get(DictTypeEnum.EXCHANGE.getDesc(), DictTypeEnum.EXCHANGE.getDesc()).getValue()));
		if(mapper.updateMyBean(client)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"数据异常!");
		}
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.RECHARGE_BEAN, MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_BEAN, amount) ,ConsumeLevelTypeEnum.BEAN,  client.getBBean().intValue(), amount,ConsumeTypeEnum.OUTCOME,null);
		return client;
	}
	
	/**
	 * 唐钻支付任务保证金
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean payTaksDepositAmountByDiamond(Long clientId, Long taskId,Integer number) {
		Task task=taskService.get(taskId);
		if(task==null){
			Shift.fatal(StatusCode.PRODUCT_NOT_EXITS, "商品不存在");
		}
		if(task.getEndTime()!=null&&OffsetDateTime.now().isAfter(task.getEndTime())){//
			Shift.fatal(StatusCode.EXCEED_PURCHASE_TIME, "已超过购买时间,欢迎下次购买");
		}
		if(task.getStartTime()!=null&&OffsetDateTime.now().isBefore(task.getStartTime())){//
			Shift.fatal(StatusCode.NO_PURCHASE_TIME, "未到购买时间,请稍后购买");
		}
		ClientTask clientActivity=new ClientTask();
		clientActivity.setTaskId(taskId);
		clientActivity.setClientId(clientId);
		if(clientTaskService.count(clientActivity)>0){
			Shift.fatal(StatusCode.ORADE_BU_ACTIVITY, "用户已经领取活动!");
		}
		Client client=new Client();
		client.setId(clientId);
		client.setTaskDepositAmount(task.getDepositAmount().multiply(new BigDecimal(number)));
		if(mapper.updateTaskDepositAmount(client)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"唐豆豆数量不够!");
		}
		if(!taskService.buyTask(task, clientId,number)){
			Shift.fatal(StatusCode.INSUFFICIENT_STOCK, "该任务已罄售,欢迎下次领取");
		}
		//step: 将钱转入到系统钻石账户
		systemDiamondService.insertDiamond(clientId,taskId,task.getDepositAmount().multiply(new BigDecimal(number)).intValue(),3);
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.BUG_TASK,MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_TASK_DIAMOND, task.getDepositAmount().multiply(new BigDecimal(number)).intValue()) ,ConsumeLevelTypeEnum.DIAMOND, task.getDepositAmount().multiply(new BigDecimal(number)).intValue(), null,ConsumeTypeEnum.OUTCOME,null);
		return true;
	}
	
	
	/**
	 * 唐豆豆支付任务保证金
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean payTaksDepositAmount(Long clientId, Long taskId,Integer number) {
		Task task=taskService.get(taskId);
		if(task==null){
			Shift.fatal(StatusCode.PRODUCT_NOT_EXITS, "任务不存在");
		}
		if(task.getEndTime()!=null&&OffsetDateTime.now().isAfter(task.getEndTime())){//
			Shift.fatal(StatusCode.EXCEED_PURCHASE_TIME, "已超过领取时间,欢迎下次领取");
		}
		if(task.getStartTime()!=null&&OffsetDateTime.now().isBefore(task.getStartTime())){//
			Shift.fatal(StatusCode.NO_PURCHASE_TIME, "未到领取时间,请稍后领取");
		}
		Client client=new Client();
		client.setId(clientId);
		client.setBBean(task.getDepositAmount().multiply(new BigDecimal(number)).multiply(new BigDecimal(10)));
		if(mapper.updateMyBean(client)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"唐豆豆数量不够!");
		}
		if(!taskService.buyTask(task, clientId,number)){
			Shift.fatal(StatusCode.INSUFFICIENT_STOCK, "该任务已罄售,欢迎下次领取");
		}
		//step: 将钱转入到系统bean账户
		systemBeanService.insertBean(clientId,taskId,task.getDepositAmount().multiply(new BigDecimal(number)).multiply(new BigDecimal(10)).intValue(),3);
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.BUG_TASK,MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_TASK_BEAN, task.getDepositAmount().multiply(new BigDecimal(number)).multiply(new BigDecimal(10)).intValue()) ,ConsumeLevelTypeEnum.BEAN, task.getDepositAmount().multiply(new BigDecimal(number)).multiply(new BigDecimal(10)).intValue(), null,ConsumeTypeEnum.OUTCOME,null);
		return true;
	}
	
	/**
	 * 支付任务保证金
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean payTaksDepositAmount(Long clientId, BigDecimal amount,Integer number, Long taskId, boolean hasBalancePay) {
		Task task=taskService.get(taskId);
		if(task==null){
			Shift.fatal(StatusCode.PRODUCT_NOT_EXITS, "任务不存在");
		}
		if(task.getDepositAmount().doubleValue()!=amount.doubleValue()){
			Shift.fatal(StatusCode.PRICE_DIFFER, "价格不一致,本次购买失败");
		}
		if(task.getEndTime()!=null&&OffsetDateTime.now().isAfter(task.getEndTime())){//
			Shift.fatal(StatusCode.EXCEED_PURCHASE_TIME, "已超过购买时间,欢迎下次购买");
		}
		if(task.getStartTime()!=null&&OffsetDateTime.now().isBefore(task.getStartTime())){//
			Shift.fatal(StatusCode.NO_PURCHASE_TIME, "未到购买时间,请稍后购买");
		}
		if(!taskService.buyTask(task, clientId,number)){
			Shift.fatal(StatusCode.INSUFFICIENT_STOCK, "该任务已罄售,欢迎下次领取");
		}
		if(hasBalancePay){
			if(!updateAmount(clientId, amount.multiply(new BigDecimal(-1)))){
				Shift.fatal(StatusCode.LESS_THAN_BALANCE, "余额不足!");
			}
		}
		//step: 将钱转入到系统账户
		systemAccountService.insertAccount(clientId,taskId,null, amount,SystemAccountTypeEnum.TASK);
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.BUG_TASK,MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_TASK, amount) ,ConsumeLevelTypeEnum.DIRECT_CONSUME, null, amount,ConsumeTypeEnum.OUTCOME,null);
		return true;
	}
	
	/**
	 * 余额充值
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Client buyRecharge(long clientId,BigDecimal amount){
		Client client=new Client();
		client.setId(clientId);
		client.setAmount(amount);
		if(mapper.updateAmount(client)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"数据异常!");
		}
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.RECHARGE_BALANCE, MessageFormat.format(ConsumeMessageTemplate.MSG_BUY_RECHARGE, amount) ,ConsumeLevelTypeEnum.BALANCE, null, amount,ConsumeTypeEnum.OUTCOME,null);
		return client;
	}
	
	/**
	 *  VIP充值
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Client buyVip(long clientId,BigDecimal amount){
		Client client=new Client();
		client.setId(clientId);
		client.setLastVipTime(OffsetDateTime.now());
		if((amount.doubleValue())==(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_3.getDesc()).getValue().doubleValue())){//vip_3
			client.setVipAmountId(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_3.getDesc()).getId());
			client.setLastVipExpireTime(OffsetDateTime.now().plusMonths(3));
		}else if((amount.doubleValue())==(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_6.getDesc()).getValue().doubleValue())){//vip_6
			client.setVipAmountId(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_6.getDesc()).getId());
			client.setLastVipExpireTime(OffsetDateTime.now().plusMonths(6));
		}else if((amount.doubleValue())==(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_12.getDesc()).getValue().doubleValue())){//vip_9
			client.setVipAmountId(CommonDict.get(DictTypeEnum.VIP.getDesc(), DictTypeEnum.VIP_12.getDesc()).getId());
			client.setLastVipExpireTime(OffsetDateTime.now().plusYears(1));
		}else{//金额不对
			Shift.fatal(StatusCode.RECHARGE_QUOTA_ERROR,"金额不对!");
		}
		client.setVipStatus(VipStatusEnum.VIP);
		if(mapper.update(client)<=0){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION,"数据异常!");
		}
		ClientInvitation clientInvitation=new ClientInvitation();
		clientInvitation.setPassiveClientId(clientId);
		ClientInvitation findClientInvitation=clientInvitationService.findOne(clientInvitation);
		if(findClientInvitation!=null){//当前注册用户是被别人邀请得用户
			//理解为下线得购买VIP记录
			BigDecimal decimal=CommonDict.get(DictTypeEnum.SUBORDINATE_BUG_VIP.getDesc(), DictTypeEnum.SUBORDINATE_BUG_VIP.getDesc()).getValue();
			String lable=MessageFormat.format(ConsumeMessageTemplate.MSG_SUBORDINATE_BUY_VIP, amount.divide(decimal.multiply(new BigDecimal(100))));
			consumeService.insertConsume(findClientInvitation.getPassiveClientId(),ConsumeSmallTypeEnum.SUBORDINATE_BUG_VIP,lable ,ConsumeLevelTypeEnum.INCOME, null, amount,ConsumeTypeEnum.INCOME,null);
			if(!clientAccountService.updateAccount(new ClientAccount(){
				private static final long serialVersionUID = 1L;
				{
					setClientId(findClientInvitation.getPassiveClientId());
					setFollowVipMoney(amount);
					setFollowNumber(1);
				}
			})){
				Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
			}
		}
		//自己得消费记录
		consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.BUY_VIP,MessageFormat.format(ConsumeMessageTemplate.MSG_LOOK_WECHAT, amount) ,ConsumeLevelTypeEnum.DIRECT_CONSUME, null, amount,ConsumeTypeEnum.OUTCOME,null);
		return client;
	}
	
	
	/**
	 * 签到赠送
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean signDay(long clientId){
		Client client=get(clientId);
		if(client.getLastSignTime()!=null&&client.getLastSignTime().getYear()==OffsetDateTime.now().getYear()&&client.getLastSignTime().getDayOfYear()==OffsetDateTime.now().getDayOfYear()){
			return false;
		}
		Client updateClient=new Client();
		updateClient.setId(clientId);
		updateClient.setSignCount(1);
		updateClient.setLastSignTime(OffsetDateTime.now());
		updateCount(updateClient);
		Integer payType=CommonDict.get(DictTypeEnum.SIGN_HAS_PAY_TYPE.getDesc(), DictTypeEnum.SIGN_HAS_PAY_TYPE.getDesc()).getValue().intValue();
		BigDecimal min=CommonDict.get(DictTypeEnum.SIGN_HAS_PAY_MIN.getDesc(), DictTypeEnum.SIGN_HAS_PAY_MIN.getDesc()).getValue();
		BigDecimal max=CommonDict.get(DictTypeEnum.SIGN_HAS_PAY_MAX.getDesc(), DictTypeEnum.SIGN_HAS_PAY_MAX.getDesc()).getValue();
        Integer s =new Random().nextInt(max.intValue())%(max.intValue()-min.intValue()+1) + min.intValue();  
		if(payType==1){
			if(updateMyBean(clientId, s)){
				String lable=MessageFormat.format(ConsumeMessageTemplate.MSG_SIGN_DAY_BEAN,DateTimeUtil.getSystemDate(),s);
				consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.SIGN_DAY,lable ,ConsumeLevelTypeEnum.BEAN, s, null,ConsumeTypeEnum.INCOME,null);
			}
		}else if(payType==2){
			if(updateAmount(clientId, new BigDecimal(s))){
				String lable=MessageFormat.format(ConsumeMessageTemplate.MSG_SIGN_DAY_AMOUNT,DateTimeUtil.getSystemDate(),new BigDecimal(s));
				consumeService.insertConsume(clientId,ConsumeSmallTypeEnum.SIGN_DAY,lable ,ConsumeLevelTypeEnum.BALANCE, null, new BigDecimal(s),ConsumeTypeEnum.INCOME,null);
			}
		}else{
			Shift.fatal(StatusCode.UNAVAILABLE_EXCEPTION);
		}
		return true;
	};
	
	/**
	 * 可提现金额调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean updateCashAmount(long clientId,BigDecimal cashAmount){
		Client client=new Client();
		client.setId(clientId);
		client.setCashAmount(cashAmount);
		return mapper.updateCashAmount(client)>0;
	};
	
	/**
	 * 余额调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean updateLockedDepositAmount(long clientId,BigDecimal amount){
		Client client=new Client();
		client.setId(clientId);
		client.setLocakedCashAmount(amount);
		return mapper.updateLockedDepositAmount(client)>0;
	}
	
	/**
	 * 余额调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean updateAmount(long clientId,BigDecimal amount){
		Client client=new Client();
		client.setId(clientId);
		client.setAmount(amount);
		return mapper.updateAmount(client)>0;
	}
	
	/**
	 * 唐豆豆调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Boolean updateMyBean(long clientId,Integer bean){
		Client client=new Client();
		client.setId(clientId);
		client.setBBean(new BigDecimal(bean));
		return mapper.updateMyBean(client)>0;
	}
	
	/**
	 * 押金调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Boolean updateDepositAmount(long clientId,BigDecimal depositAmount){
		Client client=new Client();
		client.setId(clientId);
		client.setDepositAmount(depositAmount);
		return mapper.updateDepositAmount(client)>0;
	}
	
	/**
	 * 调整以count结尾得数值型值
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Boolean updateCount(Client client){
		if(client.getId()==null){
			Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
		}
		return mapper.updateCount(client)>0;
	}
	
	/**
	 * 收入调整
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public Boolean updateIncomeAmount(long clientId,BigDecimal incomeAmount){
		Client client=new Client();
		client.setId(clientId);
		client.setIncomeAmount(incomeAmount);
		return mapper.updateIncomeAmount(client)>0;
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	public Client register(UserLoginRequest loginRequest) {
		Client client = new Client();
		client.setStatus(UserStatusEnum.NOMAIL);
		client.setMobile(loginRequest.getMobile());
		client.setRealAuthStatus(RealAuthStatusEnum.AUDIT);
		client.setGender(loginRequest.getGender());
		client.setNickname(loginRequest.getNikeName());
		client.setLastLoginTime(OffsetDateTime.now());
		client.setHeadImage(loginRequest.getHeadImage());
		try {
			client.setType(ClientTypeEnum.SELF);
			client.setPassword(PasswordHashUtil.createHash(loginRequest.getPassword()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (mapper.insert(client) > 0) {
			
			updateMyBean(client.getId(), 20);
			//自己得消费记录
			consumeService.insertConsume(client.getId(),ConsumeSmallTypeEnum.REGISTER,MessageFormat.format(ConsumeMessageTemplate.MSG_REGISTER, 20) ,ConsumeLevelTypeEnum.BEAN, 20, null,ConsumeTypeEnum.INCOME,null);
			
			ClientAccount clientAccount=new ClientAccount();
			clientAccount.setClientId(client.getId());
			clientAccountMapper.insert(clientAccount);
			
			if(!StringUtils.isEmpty(loginRequest.getShareCode())){
				Client findClient = new Client();
				findClient.setShareCode(loginRequest.getShareCode());
				Client clientObj = findOne(findClient);
				if(clientObj!=null){
					ClientInvitation clientInvitation=new ClientInvitation();
					clientInvitation.setClientId(clientObj.getId());
					clientInvitation.setClientShareCode(loginRequest.getShareCode());
					clientInvitation.setPassiveClientId(client.getId());
					if(clientInvitationService.insert(clientInvitation)<=0){
						Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "邀请码错误");
					}
					client.setInvitationClientId(clientObj.getId());
					//taskService.pushTaskResult(TaskTypeEnum.THREE, clientObj.getId());
				}
				if(!clientAccountService.updateAccount(new ClientAccount(){

					private static final long serialVersionUID = 1L;
					{
						setClientId(clientObj.getId());
						setFollowNumber(1);
					}
				})){
					Shift.fatal(StatusCode.INVALID_PARAMS_CONVERSION, "参数错误!");
				}
			}
			client.setShareCode(ShareCodeUtil.toSerialCode(client.getId()));
			mapper.update(client);
			return client;
		}
		return null;
	}

	public void login(Client user) {
		user.setLastVipTime(OffsetDateTime.now());
		mapper.update(user);
	}

	public List<Client> findLocationClient(Client findClient) {
		return mapper.findLocationClient(findClient);
	}

	public  boolean updateLocation(LocationRequest locationRequest, Long clientId) {
		Client oldClient=get(clientId);
		
		Client updateClient=new Client();
		updateClient.setPointLat(locationRequest.getPointLat());
		updateClient.setPointLog(locationRequest.getPointLog());
		updateClient.setHeadImage(oldClient.getHeadImage());
		updateClient.setRents(oldClient.getRents());
		updateClient.setGender(oldClient.getGender());
		updateClient.setNickname(oldClient.getNickname());
		updateClient.setId(oldClient.getId());
		update(updateClient);
		
		return true;
	}

	

}
